#include "TM1668.h"
#include "include.h"

//#define USE_VM
int TimeGap = 1;

unsigned char DATAB = 0;
unsigned char TRISB = 0;

//针脚定义需要修改,这里只是虚拟机定义，需要映射，映射不在这里
unsigned char DATABIT = 0;
#define DIOBIT  (1 << 0)
#define CLKBIT  (1 << 1)
#define STBBIT  (1 << 2)

unsigned char Dio = 3;
unsigned char Clk = 4;
unsigned char Stb = 5;

#define INIT_TRIS() TRISB &= ~0x07

const unsigned char segs[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71 };

#define M_DISP_CTRL_SETTING(en) ((0x80 + CFG_BRIGHTNESS) | (en << 3))
static void Delay(unsigned char t);

#define SETIO 0
#define NOP 1
#define NONOP 1
//and dot
//unsigned char code_DEG_TAB_UC[11] = {
//	0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7E, 0x6F };

short code_DEG_TAB_UC[11] = {
	SEGA | SEGB | SEGC | SEGD | SEGE | SEGF,
	SEGC | SEGB,
	SEGA | SEGB | SEGG | SEGE | SEGD,
	SEGA | SEGB | SEGC | SEGD | SEGG,
	SEGB | SEGC | SEGF | SEGG,						//4
	SEGA | SEGG | SEGF | SEGC | SEGD,				//5
	SEGA | SEGC | SEGD | SEGE | SEGF | SEGG,		//6
	SEGA | SEGB | SEGC,								//7
	SEGA | SEGB | SEGC | SEGD | SEGE | SEGF | SEGG, //8
	SEGA | SEGB | SEGC | SEGD | SEGF | SEGG,
	SEGH };

//0表示不进行半地址移动
//int HalfByteBias = 0;

//专门为Disp这个指令设置的函数，因为是半偏移状态
void TM1668_VmDispSetValue(int isNop, short Value)
{
	//进行set DIO输入
	if (!isNop)
	{
#ifdef MYDEBUG
		if ((1 << 3) & Value)
		{
			printf("Error Value Input in VmDispSet");
		}
#endif

		CodeStack[VmIndex()].code = Value;
		VmIndexInc(1);
	}
	else
	{
#ifdef NONOP
		return;
#endif
		if (Value < 0)
			Value = -Value;
		CodeStack[VmIndex()].code = 0;
		CodeStack[VmIndex()].code |= (1 << 7);
		CodeStack[VmIndex()].code |= (Value & 0x7F);
		VmIndexInc(2);
	}
}

void TM1668_VmStart()
{
	//这个含义是STB拉低电平
	DATABIT = (DIOBIT | CLKBIT);
	DATABIT &= ~(STBBIT);
	TM1668_VmDispSetValue(SETIO, DATABIT);
	TM1668_VmDispSetValue(NOP, 1 * TimeGap);
}

/*
	结束传输数据
*/
void TM1668_VmEnd()
{
	DATABIT = (DIOBIT | CLKBIT | STBBIT);
	TM1668_VmDispSetValue(SETIO, DATABIT);
	TM1668_VmDispSetValue(NOP, 1 * TimeGap);
}

void TM1668_VmWriteByte(unsigned char byte)
{
	unsigned char i = 0;
	for (i = 0; i < 8; i++)
	{

		DATABIT &= ~CLKBIT;
		TM1668_VmDispSetValue(SETIO, DATABIT);
		TM1668_VmDispSetValue(NOP, 1 * TimeGap);
		if (byte & 0x01)
		{
			DATABIT |= DIOBIT;
			TM1668_VmDispSetValue(SETIO, DATABIT);
		}
		else
		{
			DATABIT &= ~DIOBIT;
			TM1668_VmDispSetValue(SETIO, DATABIT);
		}
		TM1668_VmDispSetValue(NOP, 1 * TimeGap);
		DATABIT |= CLKBIT;
		TM1668_VmDispSetValue(SETIO, DATABIT);
		//one more time
		TM1668_VmDispSetValue(SETIO, DATABIT);
		byte >>= 1;
		TM1668_VmDispSetValue(NOP, 1 * TimeGap);
	}
}

unsigned char Brightness(unsigned char bright)
{
	switch (bright)
	{
	case 0:
		return DSP_OFF;
	case 1:
		return DSP_01_16;
	case 2:
		return DSP_02_16;
	case 3:
		return DSP_04_16;
	case 4:
		return DSP_10_16;
	case 5:
		return DSP_11_16;
	case 6:
		return DSP_12_16;
	case 7:
		return DSP_13_16;
	default:
		return DSP_14_16;
	}
}

//跟设置有关，7位10段发送14个数据,dio针脚，clk针脚，stb针脚, gpio port选择,0表示GPIOA 1表示GPIOB 2表示GPIOC
void TM1668_VmInit(int nBytes, char dio, char clk, char stb, char portdio,char portclk,char portstb){
	Dio = dio;
	Clk = clk;
	Stb = stb;
	static unsigned char brightness = DSP_14_16;
	VmResetISAPos();
	CodeStack[0].code = (VM_DISPLAY << 2);
	CodeStack[1].code = (dio&0x3F)|portdio<<6;
	CodeStack[2].code = (clk&0x3F)|portclk<<6;
	CodeStack[3].code = (stb&0x3F)|portstb<<6;
//	printf_s("VDIO %X VCLK %X VSTB %X  ", CodeStack[1].code, CodeStack[2].code, CodeStack[3].code);
	VmIndexInc(5);
	DATABIT = 0;

	//先低电平来整一个
	TM1668_VmEnd();

	TM1668_VmStart();
	TM1668_VmWriteByte(USE_GRID);
	TM1668_VmEnd();

	TM1668_VmStart();
	TM1668_VmWriteByte(CMD_DataWriteIncrease);
	TM1668_VmEnd();

	TM1668_VmStart();
	TM1668_VmWriteByte(ADD_00H);
	for (int i = 0; i < nBytes; i++)
	{
		TM1668_VmWriteByte(0xFF);
	}
	TM1668_VmEnd();

	TM1668_VmStart();
	TM1668_VmWriteByte(brightness);
	TM1668_VmEnd();

	CodeStack[VmIndex()].code = 1 << 6;
	VmResetISAPos();
#ifdef MYDEBUG
	printf("CodeLen: %d\n", VmIndex());
#endif
}

void TM1668_VmDispSeg(unsigned char* datas, unsigned char nBytes, unsigned char LCDBrightness)
{
	VmResetISAPos();
	CodeStack[0].code = (VM_DISPLAY << 2);
	CodeStack[1].code = (char)Dio;
	CodeStack[2].code = (char)Clk;
	CodeStack[3].code = (char)Stb;
	VmIndexInc(5);
	DATABIT = 0;


	TM1668_VmStart();
	TM1668_VmWriteByte(USE_GRID);
	TM1668_VmEnd();

	TM1668_VmStart();
	TM1668_VmWriteByte(CMD_DataWriteIncrease);
	TM1668_VmEnd();

	TM1668_VmStart();
	TM1668_VmWriteByte(ADD_00H);
	for (int i = 0; i < nBytes; i++)
	{
		TM1668_VmWriteByte(datas[i]);
	}
	TM1668_VmEnd();

	TM1668_VmStart();
	TM1668_VmWriteByte(Brightness(LCDBrightness));
	TM1668_VmEnd();

	//代码结束标记
	CodeStack[VmIndex()].code = 1 << 6;
	VmResetISAPos();
#ifdef MYDEBUG
	printf("Code Len: %d", VmIndex());
#endif
}


